﻿using System;
using System.Net;
using System.Text;

namespace __Able.Network.Utils
{
    public static class Util
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="host"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        public static IPEndPoint GetEndPoint(string host, int port)
        {
            IPAddress ipAddress;
            IPAddress.TryParse(host, out ipAddress);
            if (ipAddress == null)
            {
                try
                {
                    System.Net.IPHostEntry ipHostEntry = System.Net.Dns.GetHostEntry(host);
                    ipAddress = ipHostEntry.AddressList[0];
                }
                catch { }
            }
            return new IPEndPoint(ipAddress, port);
        }

        /**
         * QQ缺省编码方式
         */
        public const String CHARSET_DEFAULT = "GBK";
        /**
        * 密钥长度
        */
        public const int LENGTH_KEY = 16;


        static Encoding DefaultEncoding = Encoding.GetEncoding(CHARSET_DEFAULT);
        static DateTime baseDateTime = DateTime.Parse("1970-1-01 00:00:00.000");
        public static Random Random = new Random();

        /// <summary>
        /// 把字节数组从offset开始的len个字节转换成一个unsigned int，
        /// </summary>
        /// <param name="inData">字节数组</param>
        /// <param name="offset">从哪里开始转换.</param>
        /// <param name="len">转换长度, 如果len超过8则忽略后面的.</param>
        /// <returns></returns>
        public static uint GetUInt(byte[] inData, int offset, int len)
        {
            uint ret = 0;
            int end = 0;
            if (len > 8)
                end = offset + 8;
            else
                end = offset + len;
            for (int i = 0; i < end; i++)
            {
                ret <<= 8;
                ret |= (uint)inData[i];
            }
            return ret;
        }

        /// <summary>
        /// 根据某种编码方式将字节数组转换成字符串
        /// </summary>
        /// <param name="b">字节数组</param>
        /// <param name="encoding">encoding 编码方式</param>
        /// <returns> 如果encoding不支持，返回一个缺省编码的字符串</returns>
        public static string GetString(byte[] b, string encoding)
        {
            try
            {
                return Encoding.GetEncoding(encoding).GetString(b);
            }
            catch
            {
                return Encoding.Default.GetString(b);
            }
        }

        /// <summary>
        /// 根据缺省编码将字节数组转换成字符串
        /// </summary>
        /// <param name="b">字节数组</param>
        /// <returns>字符串</returns>
        public static string GetString(byte[] b)
        {
            return GetString(b, CHARSET_DEFAULT);
        }
        /// <summary>
        /// * 从buf的当前位置解析出一个字符串，直到碰到了buf的结尾
        /// * <p>
        /// * 此方法不负责调整buf位置，调用之前务必使buf当前位置处于字符串开头。在读取完成
        /// * 后，buf当前位置将位于buf最后之后
        /// * </p>
        /// * <p>
        /// * 返回的字符串将使用QQ缺省编码，一般来说就是GBK编码
        /// </summary>
        /// <param name="buf">The buf.</param>
        /// <returns></returns>
        public static string GetString(ByteBuffer buf)
        {
            ByteBuffer temp = new ByteBuffer();
            while (buf.HasRemaining())
            {
                temp.Put(buf.Get());
            }
            return GetString(temp.ToByteArray());
        }
        /// <summary>
        /// 从buf的当前位置解析出一个字符串，直到碰到了buf的结尾或者读取了len个byte之后停止
        /// 此方法不负责调整buf位置，调用之前务必使buf当前位置处于字符串开头。在读取完成
        /// * 后，buf当前位置将位于len字节之后或者最后之后
        /// </summary>
        /// <param name="b">The b.</param>
        /// <returns></returns>
        public static string GetString(ByteBuffer buf, int len)
        {
            ByteBuffer temp = new ByteBuffer();
            while (buf.HasRemaining() && len-- > 0)
            {
                temp.Put(buf.Get());
            }
            return GetString(temp.ToByteArray());
        }

        /// <summary>
        /// * 从buf的当前位置解析出一个字符串，直到碰到了delimit或者读取了maxLen个byte或者
        /// * 碰到结尾之后停止
        /// *此方法不负责调整buf位置，调用之前务必使buf当前位置处于字符串开头。在读取完成
        /// *后，buf当前位置将位于maxLen之后
        /// </summary>
        /// <param name="buf">The buf.</param>
        /// <param name="delimit">The delimit.</param>
        /// <param name="maxLen">The max len.</param>
        /// <returns></returns>
        public static String GetString(ByteBuffer buf, byte delimit, int maxLen)
        {
            ByteBuffer temp = new ByteBuffer();
            while (buf.HasRemaining() && maxLen-- > 0)
            {
                byte b = buf.Get();
                if (b == delimit)
                    break;
                else
                    temp.Put(b);
            }
            while (buf.HasRemaining() && maxLen-- > 0)
                buf.Get();
            return GetString(temp.ToByteArray());
        }
        /// <summary>
        /// 根据某种编码方式将字节数组转换成字符串
        /// </summary>
        /// <param name="b">The b.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="len">The len.</param>
        /// <param name="encoding">The encoding.</param>
        /// <returns></returns>
        public static string GetString(byte[] b, int offset, int len)
        {
            byte[] temp = new byte[len];
            Array.Copy(b, offset, temp, 0, len);
            return GetString(temp);
        }

        /// <summary>
        /// 从buf的当前位置解析出一个字符串，直到碰到一个分隔符为止，或者到了buf的结尾
        /// 此方法不负责调整buf位置，调用之前务必使buf当前位置处于字符串开头。在读取完成
        /// * 后，buf当前位置将位于分隔符之后
        /// </summary>
        /// <param name="buf">The buf.</param>
        /// <param name="delimit">The delimit.</param>
        /// <returns></returns>
        public static string GetString(ByteBuffer buf, byte delimit)
        {
            ByteBuffer temp = new ByteBuffer();
            while (buf.HasRemaining())
            {
                byte b = buf.Get();
                if (b == delimit)
                    return GetString(temp.ToByteArray());
                else
                    temp.Put(b);
            }
            return GetString(temp.ToByteArray());
        }

        /// <summary>
        /// 把字符串转换成int
        /// </summary>
        /// <param name="s">字符串</param>
        /// <param name="defaultValue">如果转换失败，返回这个值</param>
        /// <returns></returns>
        public static int GetInt(string s, int defaultValue)
        {
            int value;
            if (int.TryParse(s, out value))
            {
                return value;
            }
            else
            {
                return defaultValue;
            }
        }

        /// <summary>
        /// 字符串转二进制字数组
        /// </summary>
        /// <param name="s">The s.</param>
        /// <returns></returns>
        public static byte[] GetBytes(string s)
        {
            return DefaultEncoding.GetBytes(s);
        }

        /// <summary>一个随机产生的密钥字节数组
        /// 	<remark>abu 2008-02-18 </remark>
        /// </summary>
        /// <returns></returns>
        public static byte[] RandomKey()
        {
            byte[] key = new byte[LENGTH_KEY];
            (new Random()).NextBytes(key);
            return key;
        }

        /// <summary>
        /// 用于代替 System.currentTimeMillis()
        /// </summary>
        /// <param name="dateTime">The date time.</param>
        /// <returns></returns>
        public static long GetTimeMillis(DateTime dateTime)
        {
            return (long)(dateTime - baseDateTime).TotalMilliseconds;
        }
        /// <summary>
        /// 根据服务器返回的毫秒表示的日期，获得实际的日期
        /// Gets the date time from millis.
        /// 似乎服务器返回的日期要加上8个小时才能得到正确的 +8 时区的登录时间
        /// </summary>
        /// <param name="millis">The millis.</param>
        /// <returns></returns>
        public static DateTime GetDateTimeFromMillis(long millis)
        {
            return baseDateTime.AddTicks(millis * TimeSpan.TicksPerMillisecond).AddHours(8);
        }

        /// <summary>
        /// 判断IP是否全0
        /// </summary>
        /// <param name="ip">The ip.</param>
        /// <returns></returns>
        public static bool IsIPZero(byte[] ip)
        {
            for (int i = 0; i < ip.Length; i++)
            {
                if (ip[i] != 0)
                    return false;
            }
            return true;
        }
        /// <summary>
        /// ip的字节数组形式转为字符串形式的ip
        /// </summary>
        /// <param name="ip">The ip.</param>
        /// <returns></returns>
        public static String GetIpStringFromBytes(byte[] ip)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(ip[0] & 0xFF);
            sb.Append('.');
            sb.Append(ip[1] & 0xFF);
            sb.Append('.');
            sb.Append(ip[2] & 0xFF);
            sb.Append('.');
            sb.Append(ip[3] & 0xFF);
            return sb.ToString();
        }
        /// <summary>
        /// 转为16进制字符串
        /// </summary>
        /// <param name="bs">The bs.</param>
        /// <returns></returns>
        public static string ToHex(byte[] bs)
        {
            StringBuilder sb = new StringBuilder();
            foreach (byte b in bs)
            {
                sb.Append(b.ToString("x") + " ");
            }
            return sb.Remove(sb.Length - 1, 1).ToString();
        }

        /**
     * 从字节数组的指定位置起的len的字节转换成int型(big-endian)，如果不足4字节，高位认为是0
     *
     * @param b      字节数组
     * @param offset 转换起始位置
     * @param len    转换长度
     * @return 转换后的int
     */
        public static int GetIntFromBytes(byte[] b, int offset, int len)
        {
            if (len > 4)
                len = 4;

            int ret = 0;
            int end = offset + len;
            for (int i = offset; i < end; i++)
            {
                ret |= b[i] & 0xFF;
                if (i < end - 1)
                    ret <<= 8;
            }
            return ret;
        }
    }
}
